// PagesService.cs
// Facebook/Framework/Service
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Facebook.Service.Core;

namespace Facebook.Service {

    /// <summary>
    /// Represents the service APIs that allow access to information on Facebook pages.
    /// </summary>
    public sealed class PagesService {

        private FacebookSession _session;

        internal PagesService(FacebookSession session) {
            Debug.Assert(session != null);
            _session = session;
        }

        /// <summary>
        /// Checks if the application is installed on the page identified by the
        /// specified page ID.
        /// </summary>
        /// <param name="pageID">The page ID representing the page.</param>
        /// <returns>true if the application has been added, and false otherwise.</returns>
        public bool GetApplicationPrescence(string pageID) {
            if (String.IsNullOrEmpty(pageID)) {
                throw new ArgumentNullException("pageID");
            }

            FacebookRequest request = new FacebookRequest(_session);
            request.Parameters["page_id"] = pageID;

            FacebookResponse response = request.InvokeMethod("pages.isAppAdded");
            if (response.Status == FacebookResponseStatus.Succeeded) {
                return FacebookResponse.CoerceBoolean(response.Result);
            }

            return false;
        }

        /// <summary>
        /// Gets the requested information about the current page. This API can only
        /// be called if the application is running within the context of a page.
        /// If no fields are specified, all fields are requested.
        /// </summary>
        /// <param name="fields">The set of fields to request.</param>
        /// <returns>The specified page with the requested information; null if the page was not found.</returns>
        public PresencePage GetPage(string fields) {
            if (_session.SessionType != FacebookSessionType.PresencePage) {
                throw new ArgumentNullException("This call is only valid on a Page session.");
            }

            return GetPage(_session.UserID, fields);
        }

        /// <summary>
        /// Gets the requested information about the page identified by the
        /// specified page ID. If no fields are specified, all fields are requested.
        /// </summary>
        /// <param name="pageID">The page ID representing the page.</param>
        /// <param name="fields">The set of fields to request.</param>
        /// <returns>The specified page with the requested information; null if the page was not found.</returns>
        public PresencePage GetPage(string pageID, string fields) {
            if (String.IsNullOrEmpty(pageID)) {
                throw new ArgumentNullException("groupID");
            }

            if (String.IsNullOrEmpty(fields)) {
                fields = PresencePage.AllFields;
            }

            ICollection<PresencePage> pages = GetPages(new string[] { pageID }, fields);
            if ((pages != null) && (pages.Count != 0)) {
                foreach (PresencePage page in pages) {
                    return page;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the requested information about the pages identified by the
        /// specified page IDs. If no fields are specified, all fields are requested.
        /// </summary>
        /// <param name="pageIDs">The list of page IDs representing the pages to request.</param>
        /// <param name="fields">The set of fields to request.</param>
        /// <returns>The specified pages with the requested information.</returns>
        public ICollection<PresencePage> GetPages(ICollection<string> pageIDs, string fields) {
            if ((pageIDs == null) || (pageIDs.Count == 0)) {
                throw new ArgumentNullException("pageIDs");
            }

            if (String.IsNullOrEmpty(fields)) {
                fields = PresencePage.AllFields;
            }

            FacebookRequest request = new FacebookRequest(_session);

            StringBuilder idListBuilder = new StringBuilder();
            foreach (string id in pageIDs) {
                if (idListBuilder.Length != 0) {
                    idListBuilder.Append(",");
                }
                idListBuilder.Append(id);
            }
            request.Parameters["page_ids"] = idListBuilder.ToString();
            request.Parameters["fields"] = fields;

            FacebookResponse response = request.InvokeMethod("pages.getInfo");
            if (response.Status == FacebookResponseStatus.Succeeded) {
                List<PresencePage> pages;

                if (response.Result is ArrayList) {
                    ArrayList pageListState = (ArrayList)response.Result;

                    pages = new List<PresencePage>(pageListState.Count);
                    foreach (Hashtable pageState in pageListState) {
                        pages.Add(new PresencePage(pageState));
                    }
                }
                else if (response.Result is Hashtable) {
                    pages = new List<PresencePage>(1);
                    pages.Add(new PresencePage((Hashtable)response.Result));
                }
                else {
                    pages = new List<PresencePage>(0);
                }

                return pages;
            }

            return null;
        }

        /// <summary>
        /// Gets the requested information about the list of pages that the user is a fan of.
        /// If no fields are specified, all fields are requested.
        /// </summary>
        /// <param name="userID">The user ID representing the user.</param>
        /// <param name="fields">The set of fields to request.</param>
        /// <returns>The matching pages with the requested information.</returns>
        public ICollection<PresencePage> GetPagesByUser(string userID, string fields) {
            return GetPagesByUser(userID, fields, /* type */ null);
        }

        /// <summary>
        /// Gets the requested information about the list of pages that the user is a fan of.
        /// If no fields are specified, all fields are requested.
        /// </summary>
        /// <param name="userID">The user ID representing the user.</param>
        /// <param name="fields">The set of fields to request.</param>
        /// <param name="type">The type of pages to filter the list.</param>
        /// <returns>The matching pages with the requested information.</returns>
        public ICollection<PresencePage> GetPagesByUser(string userID, string fields, string type) {
            if (userID == null) {
                if (_session.SessionType == FacebookSessionType.User) {
                    userID = _session.UserID;
                }
                else {
                    userID = _session.PageUserID;
                }
            }

            if (String.IsNullOrEmpty(fields)) {
                fields = PresencePage.AllFields;
            }

            FacebookRequest request = new FacebookRequest(_session);
            request.Parameters["uid"] = userID;
            request.Parameters["fields"] = fields;
            if (String.IsNullOrEmpty(type) == false) {
                request.Parameters["type"] = type;
            }

            FacebookResponse response = request.InvokeMethod("pages.getInfo");
            if (response.Status == FacebookResponseStatus.Succeeded) {
                List<PresencePage> pages;

                if (response.Result is ArrayList) {
                    ArrayList pageListState = (ArrayList)response.Result;

                    pages = new List<PresencePage>(pageListState.Count);
                    foreach (Hashtable pageState in pageListState) {
                        pages.Add(new PresencePage(pageState));
                    }
                }
                else if (response.Result is Hashtable) {
                    pages = new List<PresencePage>(1);
                    pages.Add(new PresencePage((Hashtable)response.Result));
                }
                else {
                    pages = new List<PresencePage>(0);
                }

                return pages;
            }

            return null;
        }

        /*
        Is this possible? Wiki seems to imply that not passing in a session key allows
        retrieving pages that have added the app.
        /// <summary>
        /// Gets the requested information about the list of pages that have added
        /// the current application.
        /// </summary>
        /// <param name="fields">The set of fields to request.</param>
        /// <returns>The matching pages with the requested information.</returns>
        public ICollection<PresencePage> GetPagesWithApplication(string fields) {
            return null;
        }
        */
    }
}
